package com.xhwl.logistics.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xhwl.common.enums.ParamType;
import io.netty.channel.ConnectTimeoutException;
import org.apache.http.*;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.SocketTimeoutException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.ParseException;
import java.util.*;

/**
 * @author:
 * @description:
 * @date: 2021/7/1 10:06
 */
public class HttpUtils {

    private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);

    private static RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(10000).setSocketTimeout(10000).setConnectionRequestTimeout(5000).build();

    private String url;
    private Map<String, String> param;
    private int statusCode;
    private String content;
    private String xmlParam;
    private boolean isHttps;

    public boolean isHttps() {
        return isHttps;
    }

    public void setHttps(boolean isHttps) {
        this.isHttps = isHttps;
    }

    public String getXmlParam() {
        return xmlParam;
    }

    public void setXmlParam(String xmlParam) {
        this.xmlParam = xmlParam;
    }

    public HttpUtils(String url, Map<String, String> param) {
        this.url = url;
        this.param = param;
    }

    public HttpUtils(String url) {
        this.url = url;
    }

    public void setParameter(Map<String, String> map) {
        param = map;
    }

    public void addParameter(String key, String value) {
        if (param == null){
            param = new HashMap<String, String>();
            param.put(key, value);
        }
    }

    public void post() throws ClientProtocolException, IOException {
        HttpPost http = new HttpPost(url);
        setEntity(http);
        execute(http);
    }

    public void put() throws ClientProtocolException, IOException {
        HttpPut http = new HttpPut(url);
        setEntity(http);
        execute(http);
    }

    /**
     * set http post,put param
     */
    private void setEntity(HttpEntityEnclosingRequestBase http) {
        if (param != null) {
            List<NameValuePair> nvps = new LinkedList<NameValuePair>();
            for (String key : param.keySet()) {
                nvps.add(new BasicNameValuePair(key, param.get(key))); // 参数
            }
            http.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8)); // 设置参数
        }
        if (xmlParam != null) {
            http.setEntity(new StringEntity(xmlParam, Consts.UTF_8));
        }
    }

    private void execute(HttpUriRequest http) throws ClientProtocolException,
            IOException {
        CloseableHttpClient httpClient = null;
        try {
            if (isHttps) {
                SSLContext sslContext = new SSLContextBuilder()
                        .loadTrustMaterial(null, new TrustStrategy() {
                            // 信任所有
                            @Override
                            public boolean isTrusted(X509Certificate[] chain,
                                                     String authType)
                                    throws CertificateException {
                                return true;
                            }
                        }).build();
                SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                        sslContext);
                httpClient = HttpClients.custom().setSSLSocketFactory(sslsf)
                        .build();
            } else {
                httpClient = HttpClients.createDefault();
            }
            CloseableHttpResponse response = httpClient.execute(http);
            try {
                if (response != null) {
                    if (response.getStatusLine() != null) {
                        statusCode = response.getStatusLine().getStatusCode();
                    }
                    HttpEntity entity = response.getEntity();
                    // 响应内容
                    content = EntityUtils.toString(entity, Consts.UTF_8);
                }
            } finally {
                if(null != response){
                    response.close();
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(null != httpClient){
                httpClient.close();
            }

        }
    }

    public int getStatusCode() {
        return statusCode;
    }

    public String getContent() throws ParseException, IOException {
        return content;
    }


    // 通过map 或者构造参数
    private static List<BasicNameValuePair> getBasicNameValuePairByMap(Map<String, String> params) {
        List<BasicNameValuePair> pairs = new ArrayList<>();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            pairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
        }
        return pairs;
    }

    /**
     * 发送 json post 请求
     *
     * @param url
     * @return
     */
    public static <T> T sendPost(String url, Map<String, String> params, Class<T> classOfT) {
        String result = null;
        T resp = null;
        try {
            CloseableHttpClient client = null;
            CloseableHttpResponse response = null;
            try {
                HttpPost httpPost = new HttpPost(url);
                List<BasicNameValuePair> valuePairs = getBasicNameValuePairByMap(params);
                httpPost.setEntity(new UrlEncodedFormEntity(valuePairs, "UTF-8"));
                client = HttpClients.createDefault();
                long start = System.currentTimeMillis();
                response = client.execute(httpPost);
                log.info("请求：url:{},参数：{} 耗时：{}",url,params,(System.currentTimeMillis() - start));
                HttpEntity entity = response.getEntity();
                result = EntityUtils.toString(entity);
                resp = JSON.parseObject(result,classOfT);
                return resp;
            } catch (Exception e) {
                log.error("请求错误：url:{},参数：{} ",url,params);
                e.printStackTrace();
            } finally {
                if (response != null) {
                    response.close();
                }
                if (client != null) {
                    client.close();
                }
            }
        } catch (Exception e) {
            System.out.println("LOG-ERROR");
            System.out.println(result);
            e.printStackTrace();

        }
        return null;
    }
    public static String post(String url, Map<String, String> params) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(requestConfig);
        CloseableHttpResponse response = null;
        String result = null;
        List<NameValuePair> nvps = new ArrayList<>();
        params.entrySet().stream().forEach(e -> nvps.add(new BasicNameValuePair(e.getKey(), e.getValue())));
        httpPost.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8));
        long start = System.currentTimeMillis();
        try {
            response = httpClient.execute(httpPost);
            if(200 != response.getStatusLine().getStatusCode()){
                log.error("请求错误： {}   {}, 完成， 耗时 {}", url, params, (System.currentTimeMillis() - start));
            }
        } catch (SocketTimeoutException | ConnectTimeoutException e ){
            log.error("请求超时 {} {}", url, params);
            return null;
        }catch (IOException e) {
            log.error("请求错误： {}   {}, 完成， 耗时 {}", url, params, (System.currentTimeMillis() - start));
            e.printStackTrace();
        }
        HttpEntity httpEntity = response.getEntity();
        try {
            result = EntityUtils.toString(httpEntity,Consts.UTF_8);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }
    /**
     *
     * @param url
     * @param params
     * @param headersMap
     * @return
     */
    public static String post(String url, Map<String, String> params, Map<String, String> headersMap) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(requestConfig);
        CloseableHttpResponse response = null;
        String result = null;
        List<NameValuePair> nvps = new ArrayList<>();
        params.entrySet().stream().forEach(e -> nvps.add(new BasicNameValuePair(e.getKey(), e.getValue())));
        if (headersMap.size()>0) {
            for (Map.Entry<String, String> entry : headersMap.entrySet()) {
                httpPost.setHeader(entry.getKey(), entry.getValue());
            }
        }
        httpPost.setHeader("Content-Type", "application/json");
        httpPost.setHeader("Accept", "application/json");

        httpPost.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8));
        long start = System.currentTimeMillis();
        try {
            response = httpClient.execute(httpPost);
            if(200 != response.getStatusLine().getStatusCode()){
                log.error("请求错误： {}   {}, 完成， 耗时 {}", url, params, (System.currentTimeMillis() - start));
            }
        } catch (SocketTimeoutException | ConnectTimeoutException e ){
            log.error("请求超时 {} {}", url, params);
            return null;
        }catch (IOException e) {
            log.error("请求错误： {}   {}, 完成， 耗时 {}", url, params, (System.currentTimeMillis() - start));
            e.printStackTrace();
        }
        HttpEntity httpEntity = response.getEntity();
        try {
            result = EntityUtils.toString(httpEntity);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     *
     * @param url
     * @param json
     * @param headersMap
     * @return
     */
    public static JSONObject doPost(String url, String json,Map<String, String> headersMap) {
        HttpPost post = new HttpPost(url);
        post.setHeader("Content-Type", "application/json");
        post.setHeader("Accept", "application/json");
        if (headersMap.size()>0) {
            for (Map.Entry<String, String> entry : headersMap.entrySet()) {
                post.setHeader(entry.getKey(), entry.getValue());
            }
        }
        JSONObject response = null;
        try {
            log.info("请求： {}, 参数： {}", url, json);
            StringEntity s = new StringEntity(json, "UTF-8"); // 中文乱码在此解决
            s.setContentType("application/json");
            post.setEntity(s);
            long start = System.currentTimeMillis();
            HttpResponse res = HttpClients.createDefault().execute(post);
            log.info("请求： {}   {}, 完成， 耗时 {}", url, json, (System.currentTimeMillis() - start));
            if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                String result = EntityUtils.toString(res.getEntity());// 返回json格式：
                response = JSON.parseObject(result);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return response;
    }

    /**
     *
     * @param url
     * @param json
     * @return
     */
    public static String jsonPost(String url, String json){
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(requestConfig);
        CloseableHttpResponse response = null;
        String result = null;

        httpPost.setHeader(HTTP.CONTENT_TYPE, ParamType.JSON.contentType);
        StringEntity stringEntity = null;
        try {
            stringEntity = new StringEntity(json);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        stringEntity.setContentEncoding("UTF-8");
        stringEntity.setContentType(ParamType.JSON.contentType);
        httpPost.setEntity(stringEntity);

        try {
            log.info("请求： {}, 参数： {}", url, json);
            long start = System.currentTimeMillis();
            response = httpClient.execute(httpPost);
            log.info("请求： {}   {}, 完成， 耗时 {}", url, json, (System.currentTimeMillis() - start));
        } catch (IOException e) {
            e.printStackTrace();
        }
        HttpEntity httpEntity = response.getEntity();

        try {
            result = EntityUtils.toString(httpEntity, "UTF-8");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }



}
